package com.example.demo.java8.time;
import cn.hutool.core.date.DateTime;
import org.junit.Test;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;


public class Jdk8DateTimeTest2 {


    /**
     * 测试LocalDate 只包含年月日
     */
    @Test
    public void testLocalDate() {
        //获得当前时间
        LocalDate localDate = LocalDate.now();
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println(localDate);//2020-06-14
        System.out.println(localDateTime);//2021-01-21T11:02:29.595
        System.out.println(localDateTime.toString());//2021-01-21T11:02:29.595

        //获得月份中的第几天
        int dayOfMonth = localDate.getDayOfMonth();
        System.out.println(dayOfMonth);//14

        //获取指定日期的时间
        LocalDate date = LocalDate.of(2020, 2, 22);
        System.out.println(date); //2020-02-22

        //不会改变原来的日期，生成新的日期
        LocalDate localDate1 = localDate.plusDays(20);
        System.out.println(localDate);//2020-06-14
        System.out.println(localDate1);//2020-07-04
    }


    /**
     * 测试LocalTime 只包含时分秒
     */
    @Test
    public void testLocalTime() {
        //获得当前时间  不包括年月日
        LocalTime localTime = LocalTime.now();
        System.out.println(localTime);//15:49:06.799

        //获取时分秒
        int hour = localTime.getHour();
        int minute = localTime.getMinute();
        int second = localTime.getSecond();
        //hour:15,minute:49,second:6
        System.out.println("hour:" + hour + ",minute:" + minute + ",second:" + second);

        //指定时间
        LocalTime time = LocalTime.of(12, 22);
        System.out.println(time);//12:22

        //不会改变原来的时间，生成新的时间
        LocalTime localTime1 = localTime.plusHours(20);
        System.out.println(localTime);//15:50:26.446
        System.out.println(localTime1);//11:50:26.446
    }

    /**
     * 测试LocalDateTime 包含年月日 时分秒
     */
    @Test
    public void testLocalDateTime() {
//        //获取现在的时间  三种方式
//        System.out.println(LocalDateTime.now());//2020-06-08T11:17:04.824
//        System.out.println(LocalDate.now());//2020-06-08
//        System.out.println(LocalTime.now());//11:17:04.825
//
//        //获得当前时间
//        LocalDateTime localDateTime = LocalDateTime.now();
//        System.out.println(localDateTime);//2020-06-14T15:58:53.639
//
//        //获取年月日 时分秒
//        int year = localDateTime.getYear();
//        Month month = localDateTime.getMonth();
//        int day = localDateTime.getDayOfMonth();
//        int hour = localDateTime.getHour();
//        int minute = localDateTime.getMinute();
//        int second = localDateTime.getSecond();
//
//        //指定日期时间
//        LocalDateTime localDateTime1 = LocalDateTime.of(2020, 2, 22, 2, 22, 22);
//        System.out.println(localDateTime1);//2020-02-22T02:22:22

        //分钟
        LocalDateTime e = LocalDateTime.now();
        LocalDateTime startTimeMinute=LocalDateTime.of(e.getYear(),e.getMonth(),e.getDayOfMonth(),e.getHour(),e.getMinute(),0);
        LocalDateTime endTimeMinute=LocalDateTime.of(e.getYear(),e.getMonth(),e.getDayOfMonth(),e.getHour(),e.getMinute(),59);
        System.out.println(e);
        System.out.println(startTimeMinute);
        System.out.println(endTimeMinute);
        System.out.println(e.isBefore(endTimeMinute));
        System.out.println(e.isAfter(startTimeMinute));
        System.out.println("==============分=================");

        //小时
        LocalDateTime e1 = LocalDateTime.now();
        LocalDateTime startTimeMinute1=LocalDateTime.of(e1.getYear(),e1.getMonth(),e1.getDayOfMonth(),e1.getHour(),0,0);
        LocalDateTime endTimeMinute1=LocalDateTime.of(e1.getYear(),e1.getMonth(),e1.getDayOfMonth(),e1.getHour(),59,59);
        System.out.println(e1);
        System.out.println(startTimeMinute1);
        System.out.println(endTimeMinute1);
        System.out.println(e.isBefore(endTimeMinute1));
        System.out.println(e.isAfter(startTimeMinute1));
        System.out.println("==============时=================");
        //天
        LocalDateTime e2 = LocalDateTime.now();
        LocalDateTime startTimeMinute2=LocalDateTime.of(e2.getYear(),e2.getMonth(),e2.getDayOfMonth(),0,0,0);
        LocalDateTime endTimeMinute2=LocalDateTime.of(e2.getYear(),e2.getMonth(),e2.getDayOfMonth(),23,59,59);
        System.out.println(e2);
        System.out.println(startTimeMinute2);
        System.out.println(endTimeMinute2);
        System.out.println(e.isBefore(endTimeMinute2));
        System.out.println(e.isAfter(startTimeMinute2));
        System.out.println("==============天=================");
        //周
        LocalDateTime e3 = LocalDateTime.now();
        LocalDateTime monday=e3.with(TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY));
        LocalDateTime sunday=e3.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY ));
        LocalDateTime startTimeMinute3=LocalDateTime.of(monday.getYear(),monday.getMonth(),monday.getDayOfMonth(),0,0,0);
        LocalDateTime endTimeMinute3=LocalDateTime.of(sunday.getYear(),sunday.getMonth(),sunday.getDayOfMonth(),23,59,59);
        System.out.println(e3);
        System.out.println(startTimeMinute3);
        System.out.println(endTimeMinute3);
        System.out.println(e.isBefore(endTimeMinute3));
        System.out.println(e.isAfter(startTimeMinute3));
        System.out.println("==============周=================");
        //月
        LocalDateTime localDateTime=LocalDateTime.now();
        LocalDate today = localDateTime.toLocalDate();
        LocalDate firstDay = LocalDate.of(today.getYear(), today.getMonth(), 1);
        LocalDate lastDay = today.with(TemporalAdjusters.lastDayOfMonth());
        LocalDateTime startTime = LocalDateTime.of(firstDay, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(lastDay, LocalTime.MAX);
        System.out.println(startTime);
        System.out.println(endTime);
        System.out.println(localDateTime.isBefore(endTime));
        System.out.println(localDateTime.isAfter(startTime));

    }

    @Test
    public void testChange(){
        Date date = new Date();
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();

        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        System.out.println("Date = " + date);
        System.out.println("LocalDateTime = " + localDateTime);

        date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    /**
     * 不同的方式获取现在的时间
     */
    @Test
    public void testGetNowTime() {
        System.out.println(LocalDate.now());//2020-06-08
        System.out.println(LocalDateTime.now());//2020-06-08T11:39:09.330
        System.out.println(LocalTime.now());//11:39:09.331
        System.out.println(Instant.now());//2020-06-08T03:39:09.331Z
        System.out.println(ZonedDateTime.now());//2020-06-08T11:39:09.355+08:00[Asia/Shanghai]
        System.out.println(OffsetDateTime.now().getOffset());//+08:00
        System.out.println(ZoneId.systemDefault());//Asia/Shanghai
    }

    /**
     * 时间比较
     */
    @Test
    public void compareTime() {
        //以LocalDateTime为例(LocalDate、LocalTime与此类似)
        //时间1
        LocalDateTime now = LocalDateTime.now();
        //时间2
        LocalDateTime dateTime = LocalDateTime.of(2018, 7, 12, 13, 28, 51);
        //判断前面日期是否在后面日期后
        System.out.println("A时间是否晚于B时间:" + now.isAfter(dateTime));
        //判断前面日期是否在后面日期前
        System.out.println("A时间是否早于B时间:" + now.isBefore(dateTime));
        //判断两个日期时间是否相等
        System.out.println("两个时间是否相等:" + now.isEqual(dateTime));
    }

    @Test
    public void dateFormat() {
        LocalDateTime now = LocalDateTime.now();
        //格式化
        //使用JDK自带的时间格式:ISO_DATE_TIME(默认提供了很多格式,请自行查看)
        DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME;
        String format = now.format(dtf);
        System.out.println("format=" + format);

        //指定时间格式(ofPattern()方法)
        DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");
        String format1 = now.format(dtf1);//2021年01月21日 11时08分06秒
        System.out.println(format1);

        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String format2 = now.format(dtf2);
        System.out.println(format2);//2021-01-21 11:08:06

        //解析(parse()方法)
        LocalDateTime parse = LocalDateTime.parse(format1, dtf1);
        System.out.println("parse=" + parse);

        /**
         * 多线程执行(验证线程安全性)
         * 1.返回结果正确   2.不抛异常
         */
        for (int i = 0; i < 50; i++) {
            new Thread(() -> {
                LocalDateTime parse1 = LocalDateTime.parse(format1, dtf1);
                System.out.println("parse=" + parse1);
            }).start();
        }
    }

    @Test
    public void testInstant() {
        //Instant
        // 内部保存了秒和纳秒，一般不是给用户使用的，而是方便程序做一些统计的(比如:统计方法耗时)
        Instant now = Instant.now();
        System.out.println("当前时间戳:" + now);//2020-01-13T06:48:46.267Z
        //Instant类 并没有修改年月日等操作.因为 Instant 本来就不是给用户使用的
        //Instant类:对 秒、纳秒等操作方便
        Instant plus = now.plusSeconds(20);
        System.out.println("+20秒后:" + plus);

        Instant minus = now.minusSeconds(20);
        System.out.println("-20秒后:" + minus);

        //获取秒、毫秒、纳秒
        long second = now.getEpochSecond();
        System.out.println("秒:" + second);
        int nano = now.getNano();
        System.out.println("纳秒:" + nano);
    }

    /**
     * Duration类:计算时间的差值
     */
    @Test
    public void testTimeDiff() {
        //时间1
        LocalTime now = LocalTime.now();
        //时间2
        LocalTime dateTime = LocalTime.of(8, 15, 46);
        //计算两个时间的差值
        //计算规则:让第二个参数 减去 第一个参数(位置错误可能出现负数)
        Duration duration = Duration.between(dateTime, now);
        System.out.println("相差的天数:" + duration.toDays());
        System.out.println("相差的小时数:" + duration.toHours());
        System.out.println("相差的分钟数:" + duration.toMinutes());
        // System.out.println("相差的秒数:"+duration.toSeconds());//JDK 9+ 出现(JDK8会报错误)
        System.out.println("相差的纳秒数:" + duration.toNanos());
    }

    /**
     * Period类:计算日期的差值
     */
    @Test
    public void testDateDiff() {
        //日期1
        LocalDate now = LocalDate.now();
        //日期2
        LocalDate date = LocalDate.of(1999, 5, 29);
        //计算两个日期的差值
        //计算规则:让第二个参数 减去 第一个参数(位置错误可能出现负数)
        Period period = Period.between(date, now);
        System.out.println("相差的年:" + period.getYears());
        System.out.println("相差的月:" + period.getMonths());
        System.out.println("相差的日:" + period.getDays());
    }


    /**
     * 计算两个日期之间的差值
     */
    @Test
    public void testDateDiff2() {
        //日期1
        LocalDate now = LocalDate.now();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMdd");
        //日期2
        LocalDate date = LocalDate.parse("20221130",df);
        //计算两个日期的差值
        //计算规则:让第二个参数 减去 第一个参数(位置错误可能出现负数)
        Period period = Period.between(date.withDayOfMonth(1), now.withDayOfMonth(1));
        System.out.println("相差的年:" + period.getYears());
        System.out.println("相差的月:" + period.getMonths());
        System.out.println("相差的日:" + period.getDays());
    }

    @Test
    public void testDateLastorFirst(){
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");

        LocalDateTime yearStart = now.with(TemporalAdjusters.firstDayOfYear()).with(LocalTime.MIN);
        LocalDateTime yearEnd = now.with(TemporalAdjusters.lastDayOfYear()).with(LocalTime.MAX);
        System.out.println("当前年的开始时间:" + yearStart.format(fmt));
        System.out.println("当前年的结束时间:" + yearEnd.format(fmt));

        LocalDateTime monthStart = now.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
        LocalDateTime monthEnd = now.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);
        System.out.println("当前月的开始时间:" + monthStart.format(fmt));
        System.out.println("当前月的结束时间:" + monthEnd.format(fmt));

        int dayOfWeek = now.getDayOfWeek().getValue();
        LocalDateTime weekStart = now.minusDays(dayOfWeek - 1).with(LocalTime.MIN);
        LocalDateTime weekEnd = now.plusDays(7 - dayOfWeek).with(LocalTime.MAX);
        System.out.println("当前周的开始时间:" + weekStart.format(fmt));
        System.out.println("当前周的结束时间:" + weekEnd.format(fmt));

        LocalDateTime dayStart = now.with(LocalTime.MIN);
        LocalDateTime dayEnd = now.with(LocalTime.MAX);
        System.out.println("当天的开始时间:" + dayStart.format(fmt));
        System.out.println("当天的结束时间:" + dayEnd.format(fmt));
    }
}
